#ifndef __COMPONENT_LOCOMOTION_H__
#define __COMPONENT_LOCOMOTION_H__

#include "Component.hpp"
#include "Engine/Vector2.hpp"
#include "Engine/Vector3.hpp"
#include <memory>
#include <atomic>


using namespace PocketSurvival::Engine;

namespace PocketSurvival
{
    struct ComponentCreature;
    struct ComponentLevel;

    class BlocksManager;
    class SubsystemTimeOfDay;

    struct ComponentLocomotion : public Component
    {
    protected:
        std::atomic<bool> m_lookAnglesChange = false;
        std::atomic<bool> m_walkOrderChange = false;
        std::atomic<bool> m_flyOrderChange = false;
        std::atomic<bool> m_swimOrderChange = false;
        std::atomic<bool> m_turnOrderChange = false;
        std::atomic<bool> m_lookOrderChange = false;
        std::atomic<bool> m_jumpOrderChange = false;
        std::atomic<bool> m_ladderOrderChange = false;

    public:
        ComponentCreature *componentCreature;
        ComponentLevel *componentLevel;

        SubsystemTimeOfDay *timeOfDay;

        bool isCreativeFlyEnabled;

        std::shared_ptr<Vector2> walkOrder;
        std::shared_ptr<Vector3> flyOrder;
        std::shared_ptr<Vector3> swimOrder;
        int32_t ladderValue;
        Vector2 turnOrder;
        Vector2 lookOrder;
        float jumpOrder;
        bool lookAutoLevelX;
        bool lookAutoLevelY;
        float walkSpeedWhenTurning;                 // 转弯时的步行速度
        float minFrictionFactor;                    // 最小摩擦系数
        double ladderActivationTime = 0;            // 梯形激活时间
        float swimBurstRemaining;                   // 剩余的游泳爆发
        Vector2 lookAngles;
        std::shared_ptr<Vector3> lastPosition;

        float accelerationFactor;                   // 加速因子
        float walkSpeed;                            // 步行速度
        float ladderSpeed;                          // 爬梯速度
        float jumpSpeed;                            // 跳跃速度
        float flySpeed;                             // 飞行速度
        float swimSpeed;                            // 游泳速度
        float turnSpeed;                            // 转动速度
        float lookSpeed;                            // 观察速度
        float inAirWalkFactor;                      // 空中漫步系数

        float stunTime = 0;                         // 眩晕时间

        std::shared_ptr<Vector2> lastWalkOrder;
        std::shared_ptr<Vector3> lastFlyOrder;
        std::shared_ptr<Vector3> lastSwimOrder;
        Vector2 lastTurnOrder;
        float lastJumpOrder;

        void setLookAngles(const Vector2 &angles);
        void setWalkOrder(std::shared_ptr<Vector2> theWalkOrder);
        void setFlyOrder(std::shared_ptr<Vector3> theFlyOrder);
        void setSwimOrder(std::shared_ptr<Vector3> theSwimOrder);
        void setTurnOrder(const Vector2 &theTurnOrder);
        void setLookOrder(const Vector2 &theLookOrder);
        void setJumpOrder(float value);
        void setLadderValue(int32_t value);
        
        bool tryGetLookAngle(Vector2 &angles);
        bool tryGetLadderValue(int32_t &value);
        bool tryGetFlyOrder(std::shared_ptr<Vector3> &fly);


        virtual void normalMovement(float dt);
        virtual void ladderMovement(float dt, int32_t value);

        virtual void update(float dt) override;
        static const std::string &GetName();
        virtual const std::string &getName() const override;
        virtual void load(const nlohmann::json &jsonData) override;
        virtual void save(nlohmann::json &jsonData) override;
        virtual void saveToMsgJson(nlohmann::json &jsonData) override;
    };

} // namespace PocketSurvival

#endif
